package com.yikes.srb.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yikes.srb.common.enums.ResultCodeEnum;
import com.yikes.srb.common.result.PageResult;
import com.yikes.srb.common.utils.object.BeanUtils;
import com.yikes.srb.constant.UserInfoConstant;
import com.yikes.srb.leadingModle.form.userInfo.*;
import com.yikes.srb.leadingModle.vo.LoginVO;
import com.yikes.srb.leadingModle.vo.UserIndexVO;
import com.yikes.srb.leadingModle.vo.UserInfoVO;
import com.yikes.srb.mapper.UserAccountMapper;
import com.yikes.srb.mapper.UserLoginRecordMapper;
import com.yikes.srb.pojo.entity.UserAccount;
import com.yikes.srb.pojo.entity.UserInfo;
import com.yikes.srb.mapper.UserInfoMapper;
import com.yikes.srb.pojo.entity.UserLoginRecord;
import com.yikes.srb.pojo.enums.ServiceWorkCodeEnum;
import com.yikes.srb.redis.constant.SmsConstant;
import com.yikes.srb.service.UserInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yikes.srb.web.utils.As;
import com.yikes.srb.web.utils.RegexValidateUtils;
import com.yikes.srb.web.utils.jwt.JwtUtils;
import com.yikes.srb.web.utils.password.EncryptUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;


/**
 * <p>
 * 用户基本信息 服务实现类
 * </p>
 *
 * @author guanrong.yin
 * @since 2024-12-03
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    private final RedisTemplate<String, Object> redisTemplate;

    private final UserAccountMapper userAccountMapper;

    private final UserLoginRecordMapper userLoginRecordMapper;

    @Override
    public PageResult<UserInfoVO> listPage(UserInfoQuery query) {

        Page<UserInfo> page = lambdaQuery()
                .eq(ObjectUtil.isNotNull(query.getUserType()), UserInfo::getUserType, query.getUserType())
                .like(StrUtil.isNotBlank(query.getMobile()), UserInfo::getMobile, query.getMobile())
                .like(StrUtil.isNotBlank(query.getNickName()), UserInfo::getNickName, query.getNickName())
                .like(StrUtil.isNotBlank(query.getName()), UserInfo::getName, query.getName())
                .like(StrUtil.isNotBlank(query.getIdCard()), UserInfo::getIdCard, query.getIdCard())
                .eq(ObjectUtil.isNotNull(query.getBindStatus()), UserInfo::getBindStatus, query.getBindStatus())
                .eq(ObjectUtil.isNotNull(query.getBorrowAuthStatus()), UserInfo::getBorrowAuthStatus, query.getBorrowAuthStatus())
                .like(StrUtil.isNotBlank(query.getBindCode()), UserInfo::getBindCode, query.getBindCode())
                .eq(ObjectUtil.isNotNull(query.getStatus()), UserInfo::getStatus, query.getStatus())
                .page(Page.of(query.getPageNum(), query.getPageSize()));

        List<UserInfoVO> bean = BeanUtils.toBean(page.getRecords(), UserInfoVO.class);

        return PageResult.build(page.getTotal(), page.getPages(), bean);
    }

    @Override
    public UserInfoVO infoId(Long id) {

        UserInfo userInfo = getById(id);
        UserInfoVO bean = BeanUtils.toBean(userInfo, UserInfoVO.class);
        return bean;

    }

    @Override
    public void create(UserInfoAddForm form) {

        UserInfo bean = BeanUtils.toBean(form, UserInfo.class);
        save(bean);

    }

    @Override
    public void edit(UserInfoEditForm form) {

        UserInfo bean = BeanUtils.toBean(form, UserInfo.class);
        updateById(bean);
    }

    @Override
    public void del(Long id) {
        baseMapper.deleteById(id);
    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public void verify(RegisterForm form) {

        String mobile = form.getMobile();
        String password = form.getPassword();
        String code = form.getCode();

        //MOBILE_NULL_ERROR(-202, "手机号不能为空"),
        As.isNotBlank(mobile, ServiceWorkCodeEnum.MOBILE_NULL_ERROR);

        //MOBILE_ERROR(-203, "手机号不正确"),
        As.isTure(RegexValidateUtils.checkCellphone(mobile), ServiceWorkCodeEnum.MOBILE_ERROR);

        //PASSWORD_NULL_ERROR(-204, "密码不能为空"),
        As.isNotBlank(password, ServiceWorkCodeEnum.PASSWORD_NULL_ERROR);

        //CODE_NULL_ERROR(-205, "验证码不能为空"),
        As.isNotBlank(code, ServiceWorkCodeEnum.CODE_NULL_ERROR);

        //校验验证码
        String codeGen = (String) redisTemplate.opsForValue().get(SmsConstant.SMS_CODE_PREFIX + mobile);
        //CODE_ERROR(-206, "验证码不正确"),
        As.isEq(code, codeGen, ServiceWorkCodeEnum.CODE_ERROR);

    }

    @Override
    public void register(RegisterForm form) {

        //判断用户是否被注册
        Long count = baseMapper.selectCount(lambdaQuery().eq(UserInfo::getMobile, form.getMobile()));
        As.isTure(count == 0L, ServiceWorkCodeEnum.MOBILE_EXIST_ERROR);

        //插入用户基本信息
        UserInfo userInfo = new UserInfo();
        userInfo.setUserType(form.getUserType());
        userInfo.setNickName(form.getMobile());
        userInfo.setName(form.getMobile());
        userInfo.setMobile(form.getMobile());
        userInfo.setPassword(EncryptUtil.AESEncrypt(form.getPassword()));

        //正常
        userInfo.setStatus(UserInfoConstant.STATUS_NORMAL);
        //设置一张静态资源服务器上的头像图片
        baseMapper.insert(userInfo);

        //创建会员账户
        UserAccount userAccount = new UserAccount();
        userAccount.setUserId(userInfo.getId());
        userAccountMapper.insert(userAccount);

    }

    @Transactional(rollbackFor = {Exception.class})
    @Override
    public LoginVO login(LoginForm form, String ip) {

        String mobile = form.getMobile();
        String password = form.getPassword();
        Integer userType = form.getUserType();

        //获取会员
        UserInfo userInfo = baseMapper.selectOne(lambdaQuery().eq(UserInfo::getMobile, mobile).eq(UserInfo::getUserType, userType));

        //LOGIN_MOBILE_ERROR(-208, "用户不存在"),
        As.isNotNull(userInfo, ResultCodeEnum.USER_NOT_EXIST);
        //LOGIN_PASSWORD_ERROR(-209, "密码不正确"),
        As.isEq(EncryptUtil.AESEncrypt(password), userInfo.getPassword(), ResultCodeEnum.LOGIN_PASSWORD_ERROR);
        //LOGIN_DISABLED_ERROR(-210, "用户已被禁用"),
        As.isEq(userInfo.getStatus(), UserInfoConstant.STATUS_NORMAL, ResultCodeEnum.USER_ACCOUNT_LOCKED);

        //记录登录日志
        UserLoginRecord userLoginRecord = new UserLoginRecord();
        userLoginRecord.setUserId(userInfo.getId());
        userLoginRecord.setIp(ip);
        userLoginRecordMapper.insert(userLoginRecord);

        //生成token
        String token = JwtUtils.createToken(userInfo.getId(), userInfo.getName());
        LoginVO loginVO = new LoginVO();
        loginVO.setToken(token);
        loginVO.setName(userInfo.getName());
        loginVO.setNickName(userInfo.getNickName());
        loginVO.setHeadImg(userInfo.getHeadImg());
        loginVO.setMobile(userInfo.getMobile());
        loginVO.setUserType(userType);

        return loginVO;
    }

    @Override
    public void lock(Long id, Integer status) {

        UserInfo userInfo = this.getById(id);

        userInfo.setStatus(status);

        baseMapper.updateById(userInfo);
    }

    @Override
    public boolean checkMobile(String mobile) {

        Long count = lambdaQuery().eq(UserInfo::getMobile, mobile).count();

        return count > 0;
    }

    @Override
    public UserIndexVO getIndexUserInfo(Long userId) {

        //用户信息
        UserInfo userInfo = baseMapper.selectById(userId);

        //账户信息
        UserAccount userAccount = userAccountMapper.selectOne(new LambdaQueryWrapper<UserAccount>().eq(UserAccount::getUserId, userId));

        //登录信息
        UserLoginRecord userLoginRecord = userLoginRecordMapper.selectOne(
                new LambdaQueryWrapper<UserLoginRecord>().eq(UserLoginRecord::getUserId, userId).orderByDesc(UserLoginRecord::getId).last("limit 1")
        );

        //组装结果数据
        UserIndexVO userIndexVO = new UserIndexVO();
        userIndexVO.setUserId(userInfo.getId());
        userIndexVO.setUserType(userInfo.getUserType());
        userIndexVO.setName(userInfo.getName());
        userIndexVO.setNickName(userInfo.getNickName());
        userIndexVO.setHeadImg(userInfo.getHeadImg());
        userIndexVO.setBindStatus(userInfo.getBindStatus());
        userIndexVO.setAmount(userAccount.getAmount());
        userIndexVO.setFreezeAmount(userAccount.getFreezeAmount());
        userIndexVO.setLastLoginTime(userLoginRecord.getCreatedTime());

        return userIndexVO;
    }
}
